// vue3 响应式原理
// vue2 默认递归，不支持新增属性的响应式，数组改变length是无效的


let toProxy = new WeakMap() // 弱引用 放原对象 ：代理对象
let toRaw = new WeakMap() // 弱引用 放代理对象 ： 原对象

function isObject(target) {
    return typeof target === 'object' && target !== null
}

function hasOwn(target, key) {
    return target.hasOwnProperty(key)
}

function reactive(target) {
    return CrateReactive(target)
}


function CrateReactive(target) {
    if(!isObject(target)) { 
        return target
    }

    let proxy = toProxy.get(target)
    if(proxy) {
        return proxy
    }

    if(toRaw.has(target)) {
        return target
    }

    let Handle = {
        // Reflect的优点不会报错，进而影响后序代码的运行，而是返回boolean的值
        get(target, key, receiver) { // target是原对象， key是当前读取的值，receiver是被代理出来的对象
            console.log('获取');
            let res = Reflect.get(target, key, receiver)
            return isObject(target) ? reactive(target) : res
        },
        set(target, key, value, receiver) {
        // 怎么识别是改属性还是新增属性？
        
        let oldValue = target[key]

        let hadkey = hasOwn(target, key)

        let res = Reflect.set(target, key, value, receiver)

            if (!hadkey) { // 新增

            }
            else if(oldValue !== value) { // 修改

            }
        
        // target[key] = value // 设置成功 (如果对象不可写的话) 没有返回
        return res
    },
        deleteProperty(target, key, receiver) {
            let res = Reflect.deleteProperty(target, key)
            console.log('删除');
            return res
        }
    }
    let observed = new Proxy(target, Handle)

    // 防止多次代理
    toProxy.set(target, observed)
    toRaw.set(observed, target)
    return observed
}


// 代理对象，不需要重写对象上的key属性，value属性
let obj = {name: '曹哥'}
let proxy = reactive( // 对于多层对象，在需要读取值的时候才进行递归代理
    obj
)

// 需要记录一下这个对象如果已经被代理过，就不要再new了
// hash表 映射表 {{} => {}}

// 数组的push有两次操作，减少length那次对set的触发